package study.datastructure.link.leetcode;/**
 * @program: datastructure
 * @author: lcy
 * @create: 2024-10-11 10:26
 * <p>
 * 2024/10/11,
 */

/**
 2024/10/11,
 */

/**
 * 给你一个链表的头节点 head 和一个整数 val ，请你删除链表中所有满足 Node.val == val 的节点，并返回 新的头节点 。
 */
public class Client203 {
    //1 2 3 4 5 4 6
    //12356  (4)
    public ListNode removeElements(ListNode head, int val) {

        ListNode prev = new ListNode();
        ListNode p = head;
        while (p != null) {
            if (head.val == val) {
                head = head.next;
            }
            if (p.val == val) {
                prev.next = p.next;
            } else {
                prev = p;
            }
            p = p.next;
        }

        return head;
    }

    /**
     * 这是一个很好的问题！你的疑惑源自于引用和对象的区别。在 Java 中，node 和 dHead 是两个变量，它们都指向同一个对象。但是，当你更改 node 本身时（而不是 node.next），并不会影响 dHead。让我们通过更详细的解释来解答这个问题。
     *
     * 关键点：
     * 对象的引用：node 和 dHead 都指向同一个对象时，修改对象的内容（比如 node.next）会反映在 dHead 上。
     * 引用的重新赋值：但是，当你给 node 重新赋值（node = node.next;），只是改变了 node 本身的指向，而不会改变 dHead 的指向。
     * 让我们一步步解释：
     *
     * 初始状态
     * java
     * 复制代码
     * ListNode dHead = new ListNode(0, head); // dHead 是伪节点
     * ListNode node = dHead; // node 和 dHead 指向同一个对象
     * 在这一步，dHead 和 node 指向的是同一个 ListNode 对象。
     * 循环中的行为
     * java
     * 复制代码
     * while (node.next != null) {
     *     if (node.next.val == val) {
     *         node.next = node.next.next; // 修改链表，删除元素
     *     } else {
     *         node = node.next; // node 移动到下一个节点
     *     }
     * }
     * 当你执行 node.next = node.next.next;，你修改的是 node 所指向对象的 next 属性。因为 dHead 和 node 指向的是同一个对象，所以修改 node.next 也会影响 dHead.next。
     *
     * 但是，当你执行 node = node.next; 时，你改变的是 node 自己的指向，让它指向下一个节点。此时，dHead 仍然保持不变，继续指向原来的对象。更改 node 本身并不会影响 dHead，因为此时你只是修改了 node 的引用，而不是 dHead。
     *
     * 类比：
     * 假设你和你的朋友同时在看同一个书签标记的书（dHead 和 node 指向同一本书的同一页）。如果你修改了书上的文字（node.next = node.next.next;），那么你和朋友都会看到修改。但如果你拿着书签翻到下一页（node = node.next;），你的朋友还在看第一页（dHead 没有变）。
     *
     * 为什么 dHead 不变：
     * 在循环中，node = node.next; 只是让 node 引用的对象改变，但并不影响 dHead 的引用。
     * 你始终没有对 dHead 重新赋值，因此 dHead 始终指向伪节点，即最开始创建的那个节点。
     * 结论：
     * 当你修改 node.next，dHead 的 next 也会跟着改变，因为 node 和 dHead 初始时指向同一个对象。
     * 但当你让 node 移动到下一个节点（node = node.next;），dHead 并不会跟着改变，因为你只是在改变 node 变量的指向，而没有修改 dHead 的指向
     */
    public ListNode removeElements1(ListNode head, int val) {

        ListNode dHead = new ListNode(-1, head); //伪节点
        ListNode prev = dHead;   //哨兵
        while (prev.next != null) {
            if (prev.next.val == val) {
                prev.next = prev.next.next; //prev不动
            } else {
                prev = prev.next;
            }
        }
        return dHead.next;
    }

    /**
     * 如果相等 就返回下一个结果 忽略本结果
     * 不等 就建立连接
     * @param head
     * @param val
     * @return
     */
    public ListNode RecursionToRemoveElements1(ListNode head, int val) {
        if (head == null) {
            return null;
        }
        if (head.val == val) {
            return RecursionToRemoveElements1(head.next,val);
        }else {
            head.next=RecursionToRemoveElements1(head.next,val);
            return head;
        }
    }

}
